use std::collections::HashMap;

use chrono::Utc;
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
use serde_json::Value;

use crate::{
    boot::myerr::MyErr,
    mylib::{util, util_file, util_string},
};

const ACCESS_KEY_ID : &str = "LTAI5tQm1piRGsFxzPsY6uKJ";
const ACCESS_KEY_SECRET : &str = "9b3u9CiZdw5aWQQieTq3uUIzyRs1BA";
const ALGORITHM: &str = "ACS3-HMAC-SHA256";

const CONTENT_TYPE_URL: &str  = "application/x-www-form-urlencoded";
const CONTENT_TYPE_JSON: &str  = "application/json; charset=utf-8";
const CONTENT_TYPE_STREAM: &str  = "application/octet-stream";

#[derive(Debug)]
struct RequestBean {
    http_method: reqwest::Method,
    canonical_uri: String,
    host: String,
    x_acs_action: String,
    x_acs_version: String,
    headers: HeaderMap,
    body: String,
    body_json: serde_json::Map<String, Value>,
    body_binary: Vec<u8>,
    query_param: HashMap<String, String>,
    content_type: String,
}

/// 通过身份证照片数据方式读取身份证信息
pub async fn read_idcard_info_by_file() -> Result<String, MyErr> {
    let canonical_uri = "/".to_string();
    let host = "ocr-api.cn-hangzhou.aliyuncs.com".to_string();
    let x_acs_action = "RecognizeIdcard".to_string();
    let x_acs_version = "2021-07-07".to_string();

    let mut req = new_request(reqwest::Method::POST, canonical_uri, host, x_acs_action, x_acs_version, CONTENT_TYPE_STREAM)?;

    let mut query_param = req.query_param;
    //query_param.insert("Url".to_string(), "http://fleet.tc1680.cn/attr/img/2024-10-03/q5xn0OBblhpLXyNc.jpg".to_string()); 

    req.query_param = query_param;

    req.body_binary = util_file::read_file_binary("/home/laobu/Documents/李杰-身份证.jpg")?;


    // let mut body_map = serde_json::Map::new();
    // body_map.insert("PhoneNumbers".to_string() , json!("18677667550")); // 手机号码
    // body_map.insert("SignName".to_string() , json!("拓程科技"));    // 短信签名
    // body_map.insert("TemplateCode".to_string() , json!("SMS_473320332")); // 短信模板编号 
    // body_map.insert("TemplateParam".to_string() , json!({"name":"1234","date":"1234","money":"1234"})); 

    // let body_str = serde_json::to_string(&body_map).unwrap_or_default();  

    let a = get_authorization(&mut req).await?;

    Ok("".to_string())
}


/// 通过身份证照片URL方式读取身份证信息
pub async fn read_idcard_info_by_url() -> Result<String, MyErr> {
    let canonical_uri = "/".to_string();
    let host = "ocr-api.cn-hangzhou.aliyuncs.com".to_string();
    let x_acs_action = "RecognizeIdcard".to_string();
    let x_acs_version = "2021-07-07".to_string();

    let mut req = new_request(reqwest::Method::GET, canonical_uri, host, x_acs_action, x_acs_version, CONTENT_TYPE_URL)?;

    let mut query_param = req.query_param;
    query_param.insert("Url".to_string(), "http://fleet.tc1680.cn/attr/img/2024-10-03/q5xn0OBblhpLXyNc.jpg".to_string()); 

    req.query_param = query_param;

    // let mut body_map = serde_json::Map::new();
    // body_map.insert("PhoneNumbers".to_string() , json!("18677667550")); // 手机号码
    // body_map.insert("SignName".to_string() , json!("拓程科技"));    // 短信签名
    // body_map.insert("TemplateCode".to_string() , json!("SMS_473320332")); // 短信模板编号 
    // body_map.insert("TemplateParam".to_string() , json!({"name":"1234","date":"1234","money":"1234"})); 

    // let body_str = serde_json::to_string(&body_map).unwrap_or_default(); 
    

    let a = get_authorization(&mut req).await?;

    Ok("".to_string())
}

pub async fn send_sms() -> Result<String, MyErr> {
    let canonical_uri = "/".to_string();
    let host = "dysmsapi.aliyuncs.com".to_string();
    let x_acs_action = "SendSms".to_string();
    let x_acs_version = "2017-05-25".to_string(); 

    let mut req = new_request(reqwest::Method::GET, canonical_uri, host, x_acs_action, x_acs_version, CONTENT_TYPE_URL)?;

    let mut query_param = req.query_param;
    query_param.insert("PhoneNumbers".to_string(), "18677667550".to_string());
    query_param.insert("SignName".to_string(), "拓程科技".to_string());
    query_param.insert("TemplateCode".to_string(), "SMS_473320332".to_string());
    query_param.insert("TemplateParam".to_string(), "{\"name\":\"1234+\",\"date\":\"1234\",\"money\":\"1234\"}".to_string()); 

    req.query_param = query_param;

    // let mut body_map = serde_json::Map::new();
    // body_map.insert("PhoneNumbers".to_string() , json!("18677667550")); // 手机号码
    // body_map.insert("SignName".to_string() , json!("拓程科技"));    // 短信签名
    // body_map.insert("TemplateCode".to_string() , json!("SMS_473320332")); // 短信模板编号 
    // body_map.insert("TemplateParam".to_string() , json!({"name":"1234","date":"1234","money":"1234"})); 

    // let body_str = serde_json::to_string(&body_map).unwrap_or_default(); 

    let a = get_authorization(&mut req).await?;

    Ok("".to_string())
}

fn new_request (
    http_method: reqwest::Method,
    canonical_uri: String,
    host: String,
    x_acs_action: String,
    x_acs_version: String,
    content_type: &str,
) -> Result<RequestBean, MyErr> {
    let mut headers = HeaderMap::new();

    let now = Utc::now();
    

    let host_v = HeaderValue::from_str(&host).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    let action_v = HeaderValue::from_str(&x_acs_action).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    let version_v = HeaderValue::from_str(&x_acs_version).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    let date_v = HeaderValue::from_str(&now.format("%Y-%m-%dT%H:%M:%SZ").to_string()).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    let nonce_v = HeaderValue::from_str(&util::random_str(8)).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    let content_type_v = HeaderValue::from_str(content_type).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 

    headers.insert("host", host_v );  
    headers.insert("x-acs-action", action_v);
    headers.insert("x-acs-version", version_v);
    headers.insert("x-acs-date", date_v);
    headers.insert("x-acs-signature-nonce", nonce_v);
    headers.insert("content-type", content_type_v);
    //headers.insert("user-action", HeaderValue::from_static("asldfjalsdujfuj"));

    let req = RequestBean {
        http_method: http_method,
        canonical_uri: canonical_uri,
        host: host,
        x_acs_action: x_acs_action,
        x_acs_version: x_acs_version,
        headers: headers,
        body: "".to_string(),
        body_json: serde_json::Map::new(),
        body_binary: vec![],
        query_param: HashMap::new(),
        content_type: content_type.to_string(),
    };

    Ok(req)
}

async fn get_authorization(req: &mut RequestBean) -> Result<String, MyErr> {

    let mut canonical_query_string = String::from(""); 
    let mut query_map: Vec<(&String, &String)> = req.query_param.iter().collect();
    query_map.sort_by_key(|x| x.0);


    canonical_query_string = serde_urlencoded::to_string(query_map).unwrap_or_default();
    canonical_query_string = percent_code(&canonical_query_string);

    // for (k, v) in query_map {
    //     let ks = serde_urlencoded::to_string(k).unwrap_or_default();
    //     let vs = serde_urlencoded::to_string(v).unwrap_or_default();
    //     canonical_query_string.push_str(&percent_code(&ks));
    //     canonical_query_string.push_str("=");
    //     canonical_query_string.push_str(&percent_code(&vs));
    //     canonical_query_string.push_str("&");
    // } 
    // canonical_query_string = canonical_query_string.trim_end_matches("&").to_string();

    //println!("\n\n\n ncanonicalQueryString ===> {} \n\n\n", canonical_query_string);

    //println!("\n\n\n req.body ===> {} \n\n\n", req.body);

    let hashed_request_payload = if req.body_binary.len() > 0 {
        util_string::sha256_binary(&req.body_binary)
    } else {
        util_string::sha256(&req.body)
    }; 

    //println!("\n\n\n hashed_request_payload ===> {} \n\n\n", hashed_request_payload);

    let hashed_request_payload_v = HeaderValue::from_str(&hashed_request_payload).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    req.headers.insert("x-acs-content-sha256", hashed_request_payload_v);  

    let mut canonical_headers = String::from("");
	let mut signed_headers= String::from("");

    let mut headers_map: Vec<(&HeaderName, &HeaderValue)> = req.headers.iter().collect();
    headers_map.sort_by_key(|x| x.0.as_str());

    for (k, v) in headers_map {
        let k_low = k.as_str().to_lowercase();
        if k_low == "host" || k_low.starts_with("x-acs-") || k_low == "content-type" {
            canonical_headers.push_str(&k_low);
            canonical_headers.push_str(":");
            canonical_headers.push_str(v.to_str().unwrap_or_default());
            canonical_headers.push_str("\n");

            signed_headers.push_str(&k_low);
            signed_headers.push_str(";"); 
        } 
    } 

    signed_headers = signed_headers.trim_end_matches(";").to_string();

    //println!("\n\n\n canonical_headers ===> \n{} \n\n", canonical_headers);
    //println!("\n\n\n signed_headers ===> \n{} \n\n", signed_headers);

    //req.httpMethod + "\n" + req.canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload
    let canonical_request = format!("{}\n{}\n{}\n{}\n{}\n{}", req.http_method, req.canonical_uri, canonical_query_string, canonical_headers, signed_headers, hashed_request_payload);
    //println!("\n\n\n canonical_request ===> \n{} \n\n", canonical_request);


    let hashed_canonical_request = util_string::sha256(&canonical_request);
    let string_to_sign = format!("{}\n{}", ALGORITHM, hashed_canonical_request);
    //println!("\n\n\n string_to_sign ===> \n{} \n\n", string_to_sign);

    let signature = util_string::hmac_sha256(ACCESS_KEY_SECRET, &string_to_sign);
    //println!("\n\n\n signature ===> \n{} \n\n", signature);

    let authorization = format!("{} Credential={},SignedHeaders={},Signature={}", ALGORITHM, ACCESS_KEY_ID, signed_headers, signature);
	//println!("\n\n\n authorization ===> \n{} \n\n", authorization);

    let authorization_v = HeaderValue::from_str(&authorization).map_err(|_|MyErr::Msg("参数错误！".to_string()))?; 
    req.headers.insert("Authorization", authorization_v);  


    // let mut http_header = HeaderMap::new();
    // for (k, v) in req.headers.clone() {
    //     if let Ok(value) = HeaderValue::from_str(&v) {
    //         http_header.insert(k.clone(), value);
    //     }
    // } 

    let url = format!("https://{}{}?{}", req.host, req.canonical_uri, canonical_query_string);

    //println!("\n\n\n url ===> {:?} \n\n\n", url); 

    if req.content_type == CONTENT_TYPE_STREAM {
        let client = reqwest::Client::new();
        let rs = client.request(req.http_method.clone(), url).headers(req.headers.clone()).body(req.body_binary.clone()).send().await;
        let a = match rs {
            Ok(res) => match res.json::<serde_json::Value>().await {
                Ok(v) => {
                    //println!("\n\n\n res ===> {:?} \n\n\n", v);
                    Ok(v)
                },
                Err(e) => {
                    log::error!("读取URL数据失败！错误：{:?}  ", e );  
                    Err(MyErr::Msg("网络异常！".to_string()))
                }
            },
            Err(e) => {
                log::error!("连接url地址失败！错误：{:?}   ", e ); 
                Err(MyErr::Msg("网络异常！".to_string()))
            }
        };
    } else {
        let client = reqwest::Client::new();
        let rs = client.request(req.http_method.clone(), url).headers(req.headers.clone()).form(&req.query_param).body(req.body.clone()).send().await;
        let a = match rs {
            Ok(res) => match res.json::<serde_json::Value>().await {
                Ok(v) => {
                    //println!("\n\n\n res ===> {:?} \n\n\n", v);
                    Ok(v)
                },
                Err(e) => {
                    log::error!("读取URL数据失败！错误：{:?}  ", e );  
                    Err(MyErr::Msg("网络异常！".to_string()))
                }
            },
            Err(e) => {
                log::error!("连接url地址失败！错误：{:?}   ", e ); 
                Err(MyErr::Msg("网络异常！".to_string()))
            }
        };
    }  


    // let request = client.request(reqwest::Method::POST, url).headers(req.headers.clone()).form(&req.query_param).body(req.body.clone());
    //     let result = request
    //         .send()
    //         .await
    //         .map_err(|e| MyErr::Msg(format!("request send fail:{}", e)))?;

    // println!("\n\n\n req ===> {:?} \n\n\n", result);

    //println!("\n\n\n req ===> {:?} \n\n\n", req);

    Ok("".to_string())
}

 

/// 替换特殊字符
fn percent_code(str: &str) -> String {
    // 替换特定的编码字符
    let mut s = str.to_string();
    s = s.replace("+", "%20"); 
    s = s.replace("*", "%2A");
    s = s.replace("%7E", "~");
    return s;
}
